#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <pthread.h>
#include "thread_pool.hpp"
#include "Task.hpp"

using namespace ns_task;
using namespace ns_thread_pool;

void Usage(std::string proc)
{
    std::cout << "Usage: " << proc << " port" << std::endl;
}

// void ServiceIO(int new_sock)
// {
//     while (true)
//     {
//         char buffer[1024];
//         memset(buffer, 0, sizeof(buffer));
//         ssize_t s = read(new_sock, buffer, sizeof(buffer) - 1);
//         if (s > 0)
//         {
//             buffer[s] = 0;
//             std::cout << "client #" << buffer << std::endl;
//             std::string echo = ">>>server<<<";
//             echo += buffer;
//             write(new_sock, echo.c_str(), echo.size());
//         }
//         else if (s == 0)
//         {
//             std::cout << "client quit..." << std::endl;
//             break;
//         }
//         else
//         {
//             std::cerr << " read error" << std::endl;
//             break;
//         }
//     }
// }

// void *HandlerRequest(void *args)
// {
//     pthread_detach(pthread_self());
//     int sock = *(int*)args;
//     delete (int*)args;
//     ServiceIO(sock);
//     close(sock);
// }
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        return 1;
    }
    int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sock < 0)
    {
        std::cerr << "sock create error:" << errno << std::endl;
        return 2;
    }
    sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[1]));
    local.sin_addr.s_addr = INADDR_ANY;
    if (bind(listen_sock, (sockaddr *)&local, sizeof(local)) < 0)
    {
        std::cerr << "bind error :" << errno << std::endl;
        return 3;
    }
    const int back_log = 3;
    if (listen(listen_sock, back_log) < 0)
    {
        std::cerr << "listen error :" << errno << std::endl;
        return 4;
    }
    for (;;)
    {
        sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int new_sock = accept(listen_sock, (sockaddr *)&peer, &len);
        if (new_sock < 0)
        {
            continue;
        }
        std::cout << "get a new link->[" << inet_ntoa(peer.sin_addr) << "]" << ntohs(peer.sin_port) << std::endl;
        // version 2 多进程版本
        // pid_t id = fork();
        // if (id < 0)
        // {
        //     continue;
        // }
        // else if (id == 0)
        // {
        //     close(listen_sock);
        //     if (fork() > 0)
        //         exit(0);
        //     ServiceIO(new_sock);
        //     close(new_sock);
        //     exit(0);
        // }
        // else
        // {
        //     waitpid(id, nullptr, 0);
        //     close(new_sock);
        // }

        // version 3 多线程版本
        // pthread_t tid;
        // int *pram = new int(new_sock);
        // pthread_create(&tid, nullptr, HandlerRequest, pram);

        // version 4
        Task t(new_sock);
        ThreadPool<Task>::GetInstance()->PushTask(t);

    }
}
